package com.virtualparadigm.identity;

import java.io.Serializable;
import java.net.URI;
import java.net.URISyntaxException;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;

import com.virtualparadigm.hierarchy.LineageList;

public class ResourceIdentifier implements Serializable
{
	private static final long serialVersionUID = 1L; 
	public static String DEFAULT_SCHEME = "ri";
	
	private LineageList<ResourcePathElement> resourcePathElements; 

	//URI is being used mainly to validate the input
//	private URI uri; 
	
	public ResourceIdentifier(LineageList<ResourcePathElement> resourcePathElements) 
	{
		URI uri = ResourceAddressParser.getResourceURI(DEFAULT_SCHEME, resourcePathElements, null);
		if(uri == null)
		{
			throw new IllegalStateException("could not initialize resource identifier");
		}
		this.resourcePathElements = resourcePathElements;
	}
	
	public ResourceIdentifier(String str)
	{
		if(str != null && !str.startsWith(DEFAULT_SCHEME+":"))
		{
			throw new IllegalStateException("invalid scheme. could not initialize resource identifier");
		}
		
		try
		{
			URI uri = new URI(str);
			this.resourcePathElements = ResourceAddressParser.getResourcePathElementLineageList(uri.getAuthority(), uri.getPath());
		}
		catch(URISyntaxException urise)
		{
			urise.printStackTrace();
			throw new IllegalStateException("could not initialize resource identifier", urise);
		}
	}
	
	public LineageList<ResourcePathElement> getResourcePathElements()
	{
		return resourcePathElements;
	}

	public URI getURI()
	{
		return ResourceAddressParser.getResourceURI(DEFAULT_SCHEME, resourcePathElements, null);
	}
	
//	public String getNamespaceString()
//	{
//		String namespace = "";
//		if(this.uri != null)
//		{
//			namespace = this.uri.getAuthority();
//		}
//		return namespace;
//	}
//	
//	public String getPath()
//	{
//		String path = "";
//		if(this.uri != null)
//		{
//			path = this.uri.getPath();
//		}
//		return path;
//	}
	
//	public String getStringValue()
//	{
//		String str = null;
//		if(this.uri != null)
//		{
//			str = this.uri.toString();
//		}
//		return str;
//	}
	
	//  ================================================================
	//  UTILITY METHODS
	//  ================================================================
	public int hashCode()
	{
		HashCodeBuilder builder = new HashCodeBuilder(17,31);
	    builder.append(this.getResourcePathElements());
	    return builder.toHashCode();		
	}
	
	public boolean equals(Object obj)
	{
		if (obj == null)
		{
			return false;
		}
		if (obj == this)
		{
			return true;
		}
		if (obj.getClass() != getClass())
		{
			return false;
		}
		ResourceIdentifier that = (ResourceIdentifier)obj;
		EqualsBuilder builder = new EqualsBuilder();
	    builder.append(this.getResourcePathElements(), that.getResourcePathElements());
		return builder.isEquals();
	}
	
	public String toString()
	{
		return this.getURI().toString();
	}
	
	//  ================================================================
	//  FACTORY METHODS
	//  ================================================================
	public static ResourceIdentifier createResourceIdentifier(ResourceIdentifier parentResourceIdentifier, ResourcePathElement resourcePathElement)
	{
		ResourceIdentifier resourceIdentifier = null;
		if(parentResourceIdentifier != null && resourcePathElement != null)
		{
			try
			{
				resourceIdentifier = new ResourceIdentifier((LineageList<ResourcePathElement>)parentResourceIdentifier.getResourcePathElements().clone());
				resourceIdentifier.getResourcePathElements().queueChild(resourcePathElement);
			}
			catch(CloneNotSupportedException cnse)
			{
				cnse.printStackTrace();
			}
		}
		return resourceIdentifier;
	}
	
	
	
	public static void main(String[] args)
	{
		try
		{
			ResourceIdentifier r1 = new ResourceIdentifier(DEFAULT_SCHEME + "://bar.foo.com/c1/f1/b1");
			System.out.println("r1 initialization success");
		}
		catch(Exception e)
		{
			System.out.println("r1 initialization failed: " + e.getMessage());
		}
		
		try
		{
			ResourceIdentifier r2 = new ResourceIdentifier(DEFAULT_SCHEME + "://bar.foo.com/c1/f1/");
			System.out.println("r2 initialization success");
		}
		catch(Exception e)
		{
			System.out.println("r2 initialization failed: " + e.getMessage());
		}

		try
		{
			ResourceIdentifier r3 = new ResourceIdentifier(DEFAULT_SCHEME + "://bar.foo.com/c1/f1/b1/b3");
			System.out.println("r3 initialization success");
		}
		catch(Exception e)
		{
			System.out.println("r3 initialization failed: " + e.getMessage());
		}

		try
		{
			ResourceIdentifier r4 = new ResourceIdentifier(DEFAULT_SCHEME + "://bar.foo.com/c1/f1/b1#");
			System.out.println("r4 initialization success");
		}
		catch(Exception e)
		{
			System.out.println("r4 initialization failed: " + e.getMessage());
		}
		
	}
	
}